package com.sun.audit.extractor;

import com.sun.audit.annotation.AuditField;
import com.sun.audit.enums.BaseEnum;
import com.sun.audit.enums.DefaultEnum;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author pytho
 */
@Slf4j
public class AuditFieldExtractor {

    /**
     * 提取被 @AuditField 标记的字段名和值（批量处理）
     *
     * @param oldObjs 修改前的对象列表
     * @param newObjs 修改后的对象列表
     * @return 包含字段名和字段值的拼接结果列表
     */
    public static List<FieldExtractResult> extractAuditFieldsBatch(List<?> oldObjs, List<?> newObjs) {
        List<FieldExtractResult> results = new ArrayList<>();
        if (oldObjs == null || newObjs == null || oldObjs.size() != newObjs.size()) {
            return results;
        }
        for (int i = 0; i < oldObjs.size(); i++) {
            FieldExtractResult result = extractAuditFields(oldObjs.get(i), newObjs.get(i));
            results.add(result);
        }

        return results;
    }
    /**
     * 提取被 @AuditField 标记的字段名和值
     *
     * @return 包含字段名和字段值的拼接结果
     */
    public static FieldExtractResult extractAuditFields(Object oldObj, Object newObj) {
        if (oldObj == null || newObj == null) {
            return new FieldExtractResult("", "", "");
        }

        Class<?> clazz = oldObj.getClass();
        List<String> fieldNames = new ArrayList<>();
        List<String> fieldOldValues = new ArrayList<>();
        List<String> fieldNewValues = new ArrayList<>();

        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(AuditField.class)) {
                AuditField annotation = field.getAnnotation(AuditField.class);
                if (annotation.ignore()) {
                    continue;
                }
                try {
                    field.setAccessible(true);
                    Object oldValue = field.get(oldObj);
                    Object newValue = field.get(newObj);
                    // 获取字段显示名或默认字段名
                    String displayName = annotation.displayName().isEmpty() ?
                            field.getName() : annotation.displayName();
                    fieldNames.add(displayName);

                    // 翻译枚举字段
                    Class<? extends Enum<? extends BaseEnum>> enumType = annotation.enumType();
                    log.info("获取枚举字段类型：{}", enumType);
                    if (enumType != null && enumType != DefaultEnum.class) {
                        Method method = enumType.getMethod("getMsgByCode", Integer.class);
                        log.info("获取枚举字段值：{}", method);
                        log.info("枚举字段值1：{}", oldValue);
                        log.info("枚举字段值2：{}", newValue);
                        String oldTranslateValue = (String) method.invoke(null, Integer.valueOf(oldValue.toString()));
                        String newTranslateValue = (String) method.invoke(null, Integer.valueOf(newValue.toString()));
                        log.info("枚举字段值3：{}", oldTranslateValue);
                        log.info("枚举字段值4：{}", newTranslateValue);
                        fieldOldValues.add(oldTranslateValue != null ? oldTranslateValue : "null");
                        fieldNewValues.add(newTranslateValue != null ? newTranslateValue : "null");
                    } else {
                        fieldOldValues.add(oldValue != null ? oldValue.toString() : "null");
                        fieldNewValues.add(newValue != null ? newValue.toString() : "null");
                    }
                } catch (Exception e) {
                    log.error("解析字段错误：", e);
                }
            }
        }

        return new FieldExtractResult(
                String.join(",", fieldNames),
                String.join(",", fieldOldValues),
                String.join(",", fieldNewValues)
        );
    }

    @Getter
    public static class FieldExtractResult {
        private final String fieldNames;
        private final String fieldOldValues;
        private final String fieldNewValues;

        public FieldExtractResult(String fieldNames, String fieldOldValues, String fieldNewValues) {
            this.fieldNames = fieldNames;
            this.fieldOldValues = fieldOldValues;
            this.fieldNewValues = fieldNewValues;
        }

    }
}
